// scene.jsx — BookIt extension open animation
// Cursor clicks extension icon, popup appears. Transparent bg. Loops.

// Screen region inside the laptop bezel
const SW = 1280;  // screen width
const SH = 720;   // screen height
// Canvas size includes laptop chassis
const W = 1520;   // canvas width (includes bezel + margins)
const H = 1000;   // canvas height (includes bezel + keyboard)
const SCREEN_X = (W - SW) / 2;  // 120
const SCREEN_Y = 40;            // top bezel offset
const DURATION = 9.5;

const C = {
  ink:    '#1b2030',
  ink2:   '#3a4252',
  muted:  '#6b7280',
  mute2:  '#9aa2ae',
  line:   '#e4e6ea',
  lineSoft:'#eef0f3',
  panel:  '#ffffff',
  panelShadow: '0 20px 60px rgba(15, 23, 42, 0.12), 0 4px 12px rgba(15, 23, 42, 0.06)',
  chrome: '#f4f5f7',
  blue:   'oklch(58% 0.15 255)',
  blueSoft: 'oklch(94% 0.03 255)',
  blueMid: 'oklch(85% 0.07 255)',
};

const FONT = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';

// ── Laptop frame (MacBook-style, straight-on view) ─────────────────────────
function LaptopFrame({ children }) {
  // Laptop bezel geometry around the screen at (SCREEN_X, SCREEN_Y) size SW x SH
  const bezel = 18;                          // inner bezel (black)
  const lidPad = 14;                         // outer silver lid
  const lidX = SCREEN_X - bezel - lidPad;
  const lidY = SCREEN_Y - bezel - lidPad;
  const lidW = SW + 2 * (bezel + lidPad);
  const lidH = SH + 2 * (bezel + lidPad);
  const baseY = lidY + lidH;
  const baseW = lidW + 84;
  const baseX = (W - baseW) / 2;
  const baseH = 26;
  const notchW = 110;

  return (
    <div style={{ position: 'absolute', inset: 0 }}>
      {/* Laptop lid (silver) */}
      <div style={{
        position: 'absolute',
        left: lidX, top: lidY,
        width: lidW, height: lidH,
        background: 'linear-gradient(180deg, #d8dce1 0%, #c6cbd2 100%)',
        borderRadius: 16,
        boxShadow: '0 30px 60px rgba(15,23,42,0.18), inset 0 1px 0 rgba(255,255,255,0.6)',
      }}>
        {/* Inner bezel (black) */}
        <div style={{
          position: 'absolute',
          left: lidPad, top: lidPad,
          width: SW + 2 * bezel,
          height: SH + 2 * bezel,
          background: '#111317',
          borderRadius: 8,
          boxShadow: 'inset 0 0 0 1px rgba(255,255,255,0.04)',
        }}>
          {/* Camera dot */}
          <div style={{
            position: 'absolute', top: 6, left: '50%',
            width: 5, height: 5, borderRadius: 3,
            background: '#2c3036',
            transform: 'translateX(-50%)',
            boxShadow: 'inset 0 0 1px rgba(255,255,255,0.2)',
          }}/>
          {/* Screen area */}
          <div style={{
            position: 'absolute',
            left: bezel, top: bezel,
            width: SW, height: SH,
            overflow: 'hidden',
            borderRadius: 2,
          }}>
            {children}
          </div>
        </div>
      </div>

      {/* Hinge shadow */}
      <div style={{
        position: 'absolute',
        left: lidX + 12, top: baseY - 1,
        width: lidW - 24, height: 3,
        background: 'rgba(0,0,0,0.18)',
        filter: 'blur(1.5px)',
      }}/>

      {/* Laptop base (silver, wider than lid) */}
      <div style={{
        position: 'absolute',
        left: baseX, top: baseY,
        width: baseW, height: baseH,
        background: 'linear-gradient(180deg, #c4c9d0 0%, #a7adb5 70%, #8f959d 100%)',
        borderBottomLeftRadius: 14,
        borderBottomRightRadius: 14,
        boxShadow: '0 24px 40px rgba(15,23,42,0.22)',
      }}>
        {/* Trackpad notch */}
        <div style={{
          position: 'absolute',
          left: '50%', top: 2,
          width: notchW, height: 8,
          marginLeft: -notchW/2,
          background: 'linear-gradient(180deg, #8d939b 0%, #a7adb5 100%)',
          borderBottomLeftRadius: 4,
          borderBottomRightRadius: 4,
        }}/>
      </div>
    </div>
  );
}

// ── Cursor ──────────────────────────────────────────────────────────────────
function Cursor({ x, y, clicking = false }) {
  return (
    <div style={{
      position: 'absolute',
      left: x, top: y,
      width: 24, height: 24,
      transform: `translate(-4px, -2px) scale(${clicking ? 0.88 : 1})`,
      transition: 'transform 80ms ease-out',
      pointerEvents: 'none',
      zIndex: 200,
      filter: 'drop-shadow(0 2px 4px rgba(0,0,0,0.18))',
    }}>
      <svg width="24" height="24" viewBox="0 0 24 24" fill="none">
        <path d="M5 3 L5 19 L9 15 L11.5 20.5 L13.8 19.5 L11.3 14 L17 14 Z"
              fill="#ffffff" stroke="#1b2030" strokeWidth="1.4" strokeLinejoin="round"/>
      </svg>
    </div>
  );
}

// ── Browser chrome ──────────────────────────────────────────────────────────
function BrowserFrame({ extensionHighlight = 0, extensionPulse = 0 }) {
  return (
    <div style={{
      position: 'absolute',
      left: 0, top: 0,
      width: SW, height: SH,
      background: C.panel,
      overflow: 'hidden',
      fontFamily: FONT,
    }}>
      {/* Top bar */}
      <div style={{
        height: 52,
        background: C.chrome,
        borderBottom: '1px solid ' + C.line,
        display: 'flex',
        alignItems: 'center',
        padding: '0 18px',
        gap: 10,
      }}>
        <div style={{ width: 12, height: 12, borderRadius: 6, background: '#ff6159' }} />
        <div style={{ width: 12, height: 12, borderRadius: 6, background: '#ffbd2e' }} />
        <div style={{ width: 12, height: 12, borderRadius: 6, background: '#28c940' }} />
        <div style={{
          marginLeft: 24,
          flex: 1, maxWidth: 520, height: 30,
          background: '#fff',
          border: '1px solid ' + C.line,
          borderRadius: 8,
          display: 'flex', alignItems: 'center',
          padding: '0 12px', gap: 8,
          fontSize: 12, color: C.mute2,
        }}>
          <svg width="11" height="11" viewBox="0 0 11 11" fill="none">
            <circle cx="4.5" cy="4.5" r="3.2" stroke={C.mute2} strokeWidth="1.3"/>
            <path d="M7 7 L9.5 9.5" stroke={C.mute2} strokeWidth="1.3" strokeLinecap="round"/>
          </svg>
          <span>mail.google.com/mail/u/0/#drafts</span>
        </div>
        <div style={{ flex: 1 }} />
        <div style={{
          position: 'relative',
          width: 30, height: 30,
          borderRadius: 8,
          background: extensionHighlight > 0 ? 'rgba(88,135,242,0.10)' : 'transparent',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          transition: 'background 120ms',
        }}>
          {extensionPulse > 0 && (
            <div style={{
              position: 'absolute', inset: -4,
              borderRadius: 10,
              border: `2px solid ${C.blue}`,
              opacity: extensionPulse,
              transform: `scale(${1 + (1 - extensionPulse) * 0.6})`,
            }}/>
          )}
          <svg width="18" height="18" viewBox="0 0 18 18" fill="none">
            <path d="M7 2.5 a1.5 1.5 0 0 1 3 0 V4 h3 a1 1 0 0 1 1 1 v3 h1.5 a1.5 1.5 0 0 1 0 3 H14 v3 a1 1 0 0 1 -1 1 h-3 v-1.5 a1.5 1.5 0 0 0 -3 0 V15 H4 a1 1 0 0 1 -1 -1 v-3 H4.5 a1.5 1.5 0 0 0 0 -3 H3 V5 a1 1 0 0 1 1 -1 h3 z"
                  stroke={C.muted} strokeWidth="1.4" fill="none"/>
          </svg>
        </div>
        <div style={{
          width: 26, height: 26, borderRadius: 13,
          background: 'oklch(75% 0.08 30)',
          marginLeft: 4,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          fontSize: 10, fontWeight: 600, color: '#fff',
        }}>TM</div>
      </div>

      {/* Body: floating compose window on neutral bg */}
      <div style={{
        position: 'absolute',
        left: 0, top: 52, right: 0, bottom: 0,
        background: '#f6f7f9',
        fontFamily: FONT,
      }}>
        {/* Compose window — floating, like a mini draft */}
        <div style={{
          position: 'absolute',
          left: 80, bottom: 0,
          width: 560, height: 440,
          background: '#fff',
          borderTopLeftRadius: 10,
          borderTopRightRadius: 10,
          boxShadow: '0 -8px 28px rgba(15,23,42,0.12), 0 -2px 8px rgba(15,23,42,0.06)',
          border: '1px solid ' + C.line,
          borderBottom: 'none',
          display: 'flex', flexDirection: 'column',
        }}>
          {/* Compose title bar */}
          <div style={{
            height: 36,
            background: '#2a2f3d',
            borderTopLeftRadius: 10,
            borderTopRightRadius: 10,
            display: 'flex', alignItems: 'center',
            padding: '0 14px',
            color: '#fff', fontSize: 12, fontWeight: 500,
          }}>
            New Message
            <div style={{ flex: 1 }}/>
            <div style={{ display:'flex', gap: 12, color: 'rgba(255,255,255,0.7)', fontSize: 12 }}>
              <span>—</span><span>▢</span><span>×</span>
            </div>
          </div>

          {/* To */}
          <div style={{
            padding: '8px 14px',
            borderBottom: '1px solid ' + C.lineSoft,
            fontSize: 12, color: C.ink2,
          }}>
            <span style={{ color: C.muted }}>To </span>
            wanda@visionindustries.com
          </div>
          {/* Subject */}
          <div style={{
            padding: '8px 14px',
            borderBottom: '1px solid ' + C.lineSoft,
            fontSize: 12, fontWeight: 600, color: C.ink,
          }}>
            Demo Follow-Up
          </div>

          {/* Body */}
          <div style={{ flex: 1, padding: '12px 14px', fontSize: 12.5, color: C.ink2, lineHeight: 1.6, display: 'flex', flexDirection: 'column', gap: 8 }}>
            <div>Hi Wanda,</div>
            <div>Thanks again for taking the time to connect &amp; review a demo today. Here are the resources you requested:</div>
            <ul style={{ margin: '2px 0 2px 20px', padding: 0, color: C.blue, lineHeight: 1.7 }}>
              <li><u>Customer Case Studies</u></li>
              <li><u>G2 Reviews</u></li>
            </ul>
            <div>Here&rsquo;s a quick way to grab time with our team next week for a scoping session.</div>
            <div>Looking forward to our next conversation!</div>
            <div style={{ marginTop: 4 }}>Best,<br/>Tony</div>
          </div>

          {/* Footer */}
          <div style={{
            padding: '10px 14px',
            borderTop: '1px solid ' + C.lineSoft,
            display: 'flex', alignItems: 'center', gap: 12,
          }}>
            <div style={{
              background: C.blue, color: '#fff',
              padding: '8px 22px',
              borderRadius: 20,
              fontSize: 12, fontWeight: 500,
            }}>Send</div>
            <div style={{ display:'flex', gap: 12, color: C.mute2, fontSize: 14 }}>
              <span>A</span><span style={{transform:'rotate(-20deg)', display:'inline-block'}}>📎</span><span>🔗</span><span>😀</span>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

// ── Extension popup, populated with fake content ───────────────────────────
function ExtensionPopup({ progress, createPulse = 0 }) {
  const eased = Easing.easeOutCubic(clamp(progress, 0, 1));
  const y = -16 + eased * 16;

  return (
    <div style={{
      position: 'absolute',
      right: 78, top: 52,
      width: 340,
      background: C.panel,
      borderRadius: 14,
      boxShadow: '0 24px 64px rgba(15,23,42,0.22), 0 4px 16px rgba(15,23,42,0.08)',
      border: '1px solid ' + C.line,
      padding: 18,
      opacity: eased,
      transform: `translateY(${y}px)`,
      zIndex: 100,
      fontFamily: FONT,
      color: C.ink,
    }}>
      {/* Header */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 18 }}>
        <div style={{
          width: 28, height: 28, borderRadius: 14,
          background: C.blue,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          fontSize: 12, fontWeight: 700, color: '#fff',
          fontFamily: FONT,
        }}>B</div>
        <div style={{ fontSize: 14, fontWeight: 600, color: C.ink }}>BookIt</div>
        <div style={{ flex: 1 }} />
        <div style={{
          width: 24, height: 24, borderRadius: 12,
          background: 'oklch(75% 0.08 30)',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          fontSize: 9, fontWeight: 600, color: '#fff',
        }}>TM</div>
      </div>

      {/* Create Invite card */}
      <div style={{
        border: '1px solid ' + C.line,
        borderRadius: 10,
        padding: 14,
        marginBottom: 16,
      }}>
        <div style={{ display:'flex', alignItems:'center', gap: 8, marginBottom: 8 }}>
          <div style={{
            width: 20, height: 20, borderRadius: 4,
            background: C.blueSoft,
            display:'flex', alignItems:'center', justifyContent:'center',
          }}>
            <svg width="12" height="12" viewBox="0 0 12 12" fill="none">
              <rect x="1.5" y="2.5" width="9" height="8" rx="1" stroke={C.blue} strokeWidth="1.3"/>
              <path d="M1.5 5 H10.5" stroke={C.blue} strokeWidth="1.3"/>
              <path d="M4 1.5 V3.5 M8 1.5 V3.5" stroke={C.blue} strokeWidth="1.3" strokeLinecap="round"/>
            </svg>
          </div>
          <div style={{ fontSize: 13, fontWeight: 600 }}>New Invite</div>
        </div>
        <div style={{ fontSize: 11, color: C.muted, lineHeight: 1.45, marginBottom: 12 }}>
          Pick times from your team&rsquo;s calendars and invite guests to book a meeting.
        </div>
        <div style={{
          position: 'relative',
          height: 36,
          background: C.blue,
          borderRadius: 8,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          color: '#fff', fontSize: 13, fontWeight: 500,
          transform: `scale(${createPulse > 0 ? 1 - createPulse * 0.04 : 1})`,
          transition: 'transform 80ms',
        }}>
          Create Invite
          {createPulse > 0 && (
            <div style={{
              position: 'absolute', inset: -3,
              borderRadius: 10,
              border: `2px solid ${C.blue}`,
              opacity: createPulse * 0.7,
              transform: `scale(${1 + (1 - createPulse) * 0.15})`,
            }}/>
          )}
        </div>
      </div>

      {/* My Links */}
      <div style={{ display:'flex', alignItems:'center', gap: 6, marginBottom: 10 }}>
        <svg width="14" height="14" viewBox="0 0 14 14" fill="none">
          <path d="M5.5 8.5 L2.5 11.5 M8.5 5.5 L11.5 2.5" stroke={C.blue} strokeWidth="1.3" strokeLinecap="round"/>
          <path d="M7 4 L4 7 a2 2 0 0 0 3 3 l3-3" stroke={C.blue} strokeWidth="1.3" strokeLinejoin="round"/>
        </svg>
        <div style={{ fontSize: 13, fontWeight: 600 }}>My Links</div>
      </div>
      <div style={{ fontSize: 10, color: C.muted, marginBottom: 10, lineHeight: 1.45 }}>
        Copy a booking link below or <span style={{ color: C.blue, textDecoration:'underline' }}>create a new one</span>.
      </div>

      <div style={{ display: 'flex', flexDirection: 'column' }}>
        {[
          { title: 'Product Demo',        dur: '30 min', people: 'Tony Stark, Steve Rogers +4' },
          { title: 'Implementation Kickoff', dur: '1 hour', people: 'Larry Odinson' },
          { title: 'Qualification Call',  dur: '30 min', people: 'Natasha Romanoff, Nick Fury' },
          { title: 'Demo Follow-Up',      dur: '15 min', people: 'Tony Stark, Steve Rogers' },
        ].map((row, i, arr) => (
          <div key={i} style={{
            display: 'flex', alignItems: 'center', gap: 10,
            padding: '11px 0',
            borderBottom: i < arr.length - 1 ? '1px solid ' + C.lineSoft : 'none',
          }}>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontSize: 12, fontWeight: 600, color: C.ink, marginBottom: 3 }}>{row.title}</div>
              <div style={{ fontSize: 10, color: C.muted, marginBottom: 2 }}>{row.dur}</div>
              <div style={{ fontSize: 10, color: C.mute2, whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{row.people}</div>
            </div>
            <div style={{
              height: 26,
              padding: '0 10px',
              border: '1px solid ' + C.line,
              borderRadius: 6,
              display:'flex', alignItems:'center', gap: 5,
              fontSize: 11, color: C.ink2, fontWeight: 500,
              background: '#fff',
            }}>
              <svg width="10" height="10" viewBox="0 0 10 10" fill="none">
                <rect x="1.5" y="3" width="5" height="5.5" rx="1" stroke={C.ink2} strokeWidth="1.1"/>
                <rect x="3.5" y="1.5" width="5" height="5.5" rx="1" stroke={C.ink2} strokeWidth="1.1"/>
              </svg>
              Copy
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

// ── Calendar modal ─────────────────────────────────────────────────────────
function CalendarModal({ progress }) {
  const eased = Easing.easeOutCubic(clamp(progress, 0, 1));
  const scale = 0.94 + eased * 0.06;
  const panelW = 940;
  const panelH = 560;

  return (
    <div style={{
      position: 'absolute',
      left: (SW - panelW)/2,
      top: (SH - panelH)/2 - 10,
      width: panelW, height: panelH,
      background: C.panel,
      borderRadius: 14,
      boxShadow: '0 30px 80px rgba(15,23,42,0.28), 0 6px 20px rgba(15,23,42,0.1)',
      border: '1px solid ' + C.line,
      opacity: eased,
      transform: `scale(${scale})`,
      transformOrigin: 'center',
      display: 'flex',
      overflow: 'hidden',
      zIndex: 130,
      fontFamily: FONT,
      color: C.ink,
    }}>
      {/* Left column */}
      <div style={{
        width: 270,
        borderRight: '1px solid ' + C.lineSoft,
        padding: 18,
        display: 'flex', flexDirection: 'column', gap: 12,
        fontSize: 12,
      }}>
        <div style={{ fontSize: 12, fontWeight: 600, color: C.ink }}>Hosts (4)</div>
        {[
          { initials: 'TS', name: 'Tony Stark',      color: 'oklch(80% 0.08 30)' },
          { initials: 'SC', name: 'Sana Chan',       color: 'oklch(82% 0.07 290)' },
          { initials: 'ZF', name: 'Zara Flemmings',  color: 'oklch(82% 0.07 210)' },
          { initials: 'VP', name: 'Vanessa Peters',  color: 'oklch(82% 0.07 340)' },
        ].map((p, i) => (
          <div key={i} style={{
            height: 32,
            border: '1px solid ' + C.line,
            borderRadius: 6,
            display: 'flex', alignItems: 'center',
            padding: '0 8px', gap: 8,
            background: '#fff',
          }}>
            <div style={{
              width: 20, height: 20, borderRadius: 10,
              background: p.color,
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              fontSize: 9, fontWeight: 700, color: C.ink,
            }}>{p.initials}</div>
            <div style={{ fontSize: 11, fontWeight: 500, color: C.ink }}>{p.name}</div>
            <div style={{ flex: 1 }}/>
            <div style={{ fontSize: 11, color: C.mute2 }}>×</div>
          </div>
        ))}

        <div style={{ fontSize: 11, fontWeight: 600, color: C.ink, marginTop: 4 }}>Add Hosts</div>
        <div style={{
          height: 30, borderRadius: 6,
          border: '1px solid ' + C.line,
          background: '#fff',
          display: 'flex', alignItems: 'center',
          padding: '0 10px', fontSize: 11, color: C.muted,
        }}>Specific User</div>
        <div style={{
          height: 30, borderRadius: 6,
          border: '1px solid ' + C.line,
          background: '#fff',
          display: 'flex', alignItems: 'center',
          padding: '0 10px', fontSize: 11, color: C.mute2,
        }}>
          <svg width="10" height="10" viewBox="0 0 10 10" fill="none" style={{marginRight: 6}}>
            <circle cx="4" cy="4" r="2.8" stroke={C.mute2} strokeWidth="1.2"/>
            <path d="M6 6 L8.5 8.5" stroke={C.mute2} strokeWidth="1.2" strokeLinecap="round"/>
          </svg>
          Find a User
        </div>

        <div style={{ marginTop: 'auto', display: 'flex', flexDirection: 'column', gap: 8 }}>
          <div style={{ fontSize: 11, fontWeight: 600 }}>Select a Meeting Type</div>
          <div style={{ fontSize: 10, color: C.muted }}>Meeting Type Owner</div>
          <div style={{
            height: 30, borderRadius: 6,
            border: '1px solid ' + C.line, background: '#fff',
            display: 'flex', alignItems: 'center', padding: '0 10px',
            fontSize: 11, color: C.ink,
          }}>Tony Stark</div>
          <div style={{ fontSize: 10, color: C.muted }}>Meeting Type</div>
          <div style={{
            height: 30, borderRadius: 6,
            border: '1px solid ' + C.line, background: '#fff',
            display: 'flex', alignItems: 'center', padding: '0 10px',
            fontSize: 11, color: C.ink,
          }}>BookIt – 30 Min Demo</div>
        </div>
      </div>

      {/* Right column */}
      <div style={{ flex: 1, display: 'flex', flexDirection: 'column' }}>
        <div style={{
          padding: '18px 22px 12px',
          display: 'flex', alignItems: 'center', gap: 12,
        }}>
          <div style={{ fontSize: 16, fontWeight: 600, color: C.ink }}>Select Date and Time</div>
          <div style={{ flex: 1 }}/>
          <div style={{ fontSize: 11, color: C.muted }}>Timezone: Pacific US ▾</div>
        </div>
        <div style={{
          padding: '0 22px 10px',
          display: 'flex', alignItems: 'center', gap: 12, fontSize: 11,
        }}>
          <div style={{
            padding: '4px 12px',
            border: '1px solid ' + C.line,
            borderRadius: 6, color: C.ink,
          }}>Today</div>
          <div style={{ color: C.muted }}>‹ ›</div>
          <div style={{ fontWeight: 600, color: C.ink }}>October 5 – 11, 2025</div>
        </div>
        <CalendarGrid />
        <div style={{
          borderTop: '1px solid ' + C.lineSoft,
          padding: '12px 22px',
          display: 'flex', alignItems: 'center',
          fontSize: 11, color: C.ink,
        }}>
          <span style={{ color: C.muted }}>▾</span>
          <span style={{ marginLeft: 8, fontWeight: 600 }}>Meeting Times (2)</span>
          <div style={{ flex: 1 }}/>
          <div style={{
            padding: '8px 22px',
            background: C.blue,
            borderRadius: 8,
            color: '#fff', fontSize: 12, fontWeight: 500,
          }}>Next</div>
        </div>
      </div>

      {/* close X */}
      <div style={{
        position: 'absolute', top: 14, right: 14,
        width: 22, height: 22,
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        color: C.muted, fontSize: 14,
      }}>×</div>
    </div>
  );
}

function CalendarGrid() {
  const days = ['SUN','MON','TUE','WED','THU','FRI','SAT'];
  const dayNums = [5,6,7,8,9,10,11];
  const hours = 6;
  const cellH = 52;
  const labelW = 44;

  const events = [
    { day: 3, startH: 0,   dur: 1, color: 'oklch(92% 0.05 85)',  label: 'busy', time: '10:30 AM', accent: 'oklch(75% 0.10 85)' },
    { day: 4, startH: 0,   dur: 1, color: 'oklch(92% 0.05 290)', label: 'Demo Call', time: '10:30 AM', accent: 'oklch(75% 0.10 290)' },
    { day: 5, startH: 0,   dur: 1, color: 'oklch(92% 0.05 85)',  label: 'busy', time: '10:30 AM', accent: 'oklch(75% 0.10 85)' },
    { day: 2, startH: 1,   dur: 1, color: 'oklch(92% 0.05 255)', label: 'Weekly Sync', time: '12:00 PM', accent: 'oklch(72% 0.10 255)' },
    { day: 3, startH: 1,   dur: 1, color: 'oklch(92% 0.05 255)', label: 'Team Chat', time: '12:00 PM', accent: 'oklch(72% 0.10 255)' },
    { day: 4, startH: 1,   dur: 1, color: 'oklch(92% 0.05 255)', label: 'Weekly Scrum', time: '12:00 PM', accent: 'oklch(72% 0.10 255)' },
    { day: 3, startH: 1.5, dur: 1, color: 'oklch(92% 0.05 85)',  label: 'busy', time: '12:30 PM', accent: 'oklch(75% 0.10 85)' },
    { day: 2, startH: 2,   dur: 1, color: 'oklch(92% 0.05 30)',  label: 'One-on-one', time: '1:00 PM', accent: 'oklch(75% 0.10 30)' },
    { day: 5, startH: 2,   dur: 1, color: 'oklch(92% 0.05 30)',  label: 'Training', time: '1:00 PM', accent: 'oklch(75% 0.10 30)' },
    { day: 1, startH: 3,   dur: 1, color: 'oklch(92% 0.05 85)',  label: 'busy', time: '2:00 PM', accent: 'oklch(75% 0.10 85)' },
    { day: 3, startH: 3,   dur: 1, color: 'oklch(92% 0.05 85)',  label: 'busy', time: '2:00 PM', accent: 'oklch(75% 0.10 85)' },
  ];

  // Selected slots (always on — modal appears after selection visually)
  const selected = [
    { day: 1, startH: 1.0 }, // Mon 12:00 - but actually we'll show 11:30 style
    { day: 2, startH: 3.0 }, // Tue 2:00
  ];

  return (
    <div style={{
      flex: 1, position: 'relative',
      borderTop: '1px solid ' + C.lineSoft,
      display: 'flex',
      overflow: 'hidden',
    }}>
      <div style={{ width: labelW, borderRight: '1px solid ' + C.lineSoft }}>
        <div style={{ height: 34 }}/>
        {Array.from({length: hours}).map((_, i) => {
          const h = 11 + i;
          const display = h > 12 ? (h - 12) : h;
          const suffix = h >= 12 ? 'PM' : 'AM';
          return (
            <div key={i} style={{
              height: cellH, fontSize: 9.5, color: C.muted,
              textAlign: 'right', paddingRight: 6, paddingTop: 2,
            }}>
              {display} {suffix}
            </div>
          );
        })}
      </div>
      <div style={{ flex: 1, display: 'flex' }}>
        {days.map((d, di) => {
          const isWeekend = di === 0 || di === 6;
          return (
            <div key={di} style={{
              flex: 1,
              borderRight: di < 6 ? '1px solid ' + C.lineSoft : 'none',
              position: 'relative',
              background: isWeekend ? `repeating-linear-gradient(135deg, #f6f7f9 0 6px, #fff 6px 12px)` : '#fff',
            }}>
              <div style={{
                height: 34, borderBottom: '1px solid ' + C.lineSoft,
                display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 1,
              }}>
                <div style={{ fontSize: 9, color: C.muted, letterSpacing: '0.08em' }}>{d}</div>
                <div style={{ fontSize: 12, fontWeight: 600, color: C.ink }}>{dayNums[di]}</div>
              </div>
              {Array.from({length: hours}).map((_, hi) => (
                <div key={hi} style={{ height: cellH, borderBottom: '1px solid ' + C.lineSoft }}/>
              ))}
              {events.filter(e => e.day === di).map((e, ei) => (
                <div key={ei} style={{
                  position: 'absolute',
                  left: 3, right: 3,
                  top: 34 + e.startH * cellH + 2,
                  height: e.dur * cellH - 4,
                  background: e.color,
                  borderLeft: `2px solid ${e.accent}`,
                  borderRadius: 3,
                  padding: '3px 5px',
                  fontSize: 9, lineHeight: 1.2,
                  color: C.ink2,
                  overflow: 'hidden',
                }}>
                  <div style={{ fontWeight: 600 }}>{e.label}</div>
                  <div style={{ color: C.muted }}>{e.time}</div>
                </div>
              ))}
              {selected.filter(s => s.day === di).map((s, si) => (
                <div key={'sel'+si} style={{
                  position: 'absolute',
                  left: 3, right: 3,
                  top: 34 + s.startH * cellH + 2,
                  height: cellH - 4,
                  background: C.ink,
                  borderRadius: 3,
                  padding: '3px 5px',
                  fontSize: 9, fontWeight: 600,
                  color: '#fff',
                }}>
                  {s.startH === 1.0 ? '11:30 AM' : '2:00 PM'}
                </div>
              ))}
            </div>
          );
        })}
      </div>
    </div>
  );
}

// ── Scene orchestration ─────────────────────────────────────────────────────
function Scene() {
  const time = useTime();

  // Timeline:
  // 0.0 - 1.2  cursor → extension icon
  // 1.2        click extension
  // 1.3 - 2.1  popup drops in
  // 2.1 - 3.6  HOLD popup
  // 3.6 - 4.2  cursor → Create Invite button
  // 4.2        click Create Invite
  // 4.3 - 5.1  popup fades, modal scales in
  // 5.1 - 8.8  HOLD modal
  // 8.8 - 9.5  modal fades, reset for loop

  const cursorPath = [
    { t: 0.0,  x: 500,  y: 440 },
    { t: 1.15, x: 1190, y: 28  },  // extension icon
    { t: 1.4,  x: 1190, y: 28  },
    { t: 2.2,  x: 1110, y: 170 },
    { t: 3.6,  x: 1110, y: 200 },
    { t: 4.1,  x: 1080, y: 244 },  // Create Invite button
    { t: 4.35, x: 1080, y: 244 },
    { t: 5.4,  x: 840,  y: 420 },  // drift over modal
    { t: 8.8,  x: 840,  y: 420 },
    { t: 9.5,  x: 520,  y: 480 },
  ];

  const interp = (axis) => {
    for (let i = 0; i < cursorPath.length - 1; i++) {
      const a = cursorPath[i], b = cursorPath[i+1];
      if (time >= a.t && time <= b.t) {
        const span = b.t - a.t;
        const local = span > 0 ? (time - a.t) / span : 0;
        const eased = Easing.easeInOutCubic(local);
        return a[axis] + (b[axis] - a[axis]) * eased;
      }
    }
    return cursorPath[cursorPath.length-1][axis];
  };
  const cursorX = interp('x');
  const cursorY = interp('y');

  // Click pulse
  const clickPulse = (tc) => {
    const d = time - tc;
    if (d < 0 || d > 0.4) return 0;
    return 1 - d / 0.4;
  };
  const extPulse = clickPulse(1.2);
  const clicking = extPulse > 0.5;

  const createPulse = clickPulse(4.2);
  const clicking2 = extPulse > 0.5 || createPulse > 0.5;

  const extHoverHi = animate({ from: 0, to: 1, start: 0.8, end: 1.2 })(time);
  const popupShow = animate({ from: 0, to: 1, start: 1.3, end: 2.1, ease: Easing.easeOutCubic })(time);
  const popupFade = 1 - animate({ from: 0, to: 1, start: 4.35, end: 4.85 })(time);
  const popupVisible = popupShow * popupFade;

  const modalShow = animate({ from: 0, to: 1, start: 4.5, end: 5.2, ease: Easing.easeOutCubic })(time);
  const modalFade = 1 - animate({ from: 0, to: 1, start: 8.9, end: 9.4 })(time);
  const modalVisible = modalShow * modalFade;

  return (
    <>
      <LaptopFrame>
        <BrowserFrame extensionHighlight={extHoverHi} extensionPulse={extPulse} />

        {popupVisible > 0.01 && (
          <div style={{ opacity: popupVisible }}>
            <ExtensionPopup progress={popupShow} createPulse={createPulse} />
          </div>
        )}

      {modalVisible > 0.01 && (
          <div style={{ opacity: modalVisible }}>
            <CalendarModal progress={modalShow} />
          </div>
        )}

        <Cursor x={cursorX} y={cursorY} clicking={clicking2} />
      </LaptopFrame>
    </>
  );
}

// ── App ─────────────────────────────────────────────────────────────────────
function App() {
  const params = new URLSearchParams(window.location.search);
  const clean = params.get('clean') === '1';

  if (clean) {
    return (
      <CleanStage width={W} height={H} duration={DURATION}>
        <Scene />
      </CleanStage>
    );
  }

  return (
    <Stage
      width={W}
      height={H}
      duration={DURATION}
      background="transparent"
      persistKey="bookit-anim"
    >
      <Scene />
    </Stage>
  );
}

function CleanStage({ width, height, duration, children }) {
  const [time, setTime] = React.useState(0);
  React.useEffect(() => {
    let raf;
    let last = null;
    const step = (ts) => {
      if (last == null) last = ts;
      const dt = (ts - last) / 1000;
      last = ts;
      setTime(t => (t + dt) % duration);
      raf = requestAnimationFrame(step);
    };
    raf = requestAnimationFrame(step);
    return () => cancelAnimationFrame(raf);
  }, [duration]);
  const ctxValue = { time, duration, playing: true, setTime, setPlaying: () => {} };
  return (
    <div style={{
      position: 'fixed', inset: 0,
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      background: 'transparent',
    }}>
      <div style={{ width, height, position: 'relative', background: 'transparent' }}>
        <TimelineContext.Provider value={ctxValue}>
          {children}
        </TimelineContext.Provider>
      </div>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
